<template>
  <div>
    <a-form ref="form" :form="form" @submit="handleSubmit">
      <a-form-item>
        <a-input
          v-decorator="[
            'userName',
            { rules: [{ required: true, message: '请输入您的用户名!' }] },
          ]"
          placeholder="用户名"
          class="input"
          @focusin="inputFocus('name', 'in')"
          @focusout="inputFocus('name', 'out')"
          @mouseover="inputHover('name', 'in')"
          @mouseout="inputHover('name', 'out')"
        >
          <img
            v-if="focus === 'name' || hover === 'name'"
            slot="prefix"
            alt=""
            src="@/assets/form/user-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/user.svg" />
        </a-input>
      </a-form-item>
      <a-form-item>
        <a-input-password
          v-decorator="[
            'password',
            {
              rules: [{ validator: validateToRepeatPassword }],
            },
          ]"
          type="password"
          placeholder="密码"
          class="input"
          @focusin="inputFocus('password', 'in')"
          @focusout="inputFocus('password', 'out')"
        >
          <img
            v-if="focus === 'password' || hover === 'password'"
            slot="prefix"
            alt=""
            src="@/assets/form/lock-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/lock.svg" />
        </a-input-password>
      </a-form-item>
      <a-form-item v-if="focus === 'password' || hover === 'password'">
        <div style="margin-left: 120px;">
          <template v-for="(passwordRule, index) in passwordRuleList">
            <div
              :key="index"
              :class="
                passwordRule.rule
                  ? 'success-password-tips'
                  : 'error-password-tips'
              "
            >
              <a-icon
                theme="filled"
                style="margin-right: 6px;"
                :type="passwordRule.rule ? 'check-circle' : 'close-circle'"
              />{{ passwordRule.text }}
            </div>
          </template>
        </div>
      </a-form-item>
      <a-form-item>
        <a-input-password
          v-decorator="[
            'repeatPassword',
            {
              rules: [
                {
                  validator: checkRepeatPassword,
                },
              ],
            },
          ]"
          type="password"
          placeholder="确认密码"
          class="input"
          @focusin="inputFocus('repeatPassword', 'in')"
          @focusout="inputFocus('repeatPassword', 'out')"
          @mouseover="inputHover('repeatPassword', 'in')"
          @mouseout="inputHover('repeatPassword', 'out')"
        >
          <img
            v-if="focus === 'repeatPassword' || hover === 'password'"
            slot="prefix"
            alt=""
            src="@/assets/form/lock-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/lock.svg" />
        </a-input-password>
      </a-form-item>
      <!-- <a-form-item>
        <a-input
          v-decorator="[
            'email',
            {
              rules: [
                {
                  type: 'email',
                  message: '请输入正确的邮箱!',
                },
                {
                  required: true,
                  message: '请输入您的邮箱!',
                },
              ],
            },
          ]"
          placeholder="邮箱"
          class="input"
          @focusin="inputFocus('mail', 'in')"
          @focusout="inputFocus('mail', 'out')"
          @mouseover="inputHover('mail', 'in')"
          @mouseout="inputHover('mail', 'out')"
        >
          <img
            v-if="focus === 'mail' || hover === 'mail'"
            slot="prefix"
            alt=""
            src="@/assets/form/mail-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/mail.svg" />
        </a-input>
      </a-form-item> -->
      <a-form-item>
        <a-input
          v-decorator="[
            'telephone',
            { rules: [{ validator: validateTelephoneNumber }] },
          ]"
          type="telephone"
          placeholder="手机号"
          class="input telephone-input"
          @focusin="inputFocus('telephone', 'in')"
          @focusout="inputFocus('telephone', 'out')"
          @mouseover="inputHover('telephone', 'in')"
          @mouseout="inputHover('telephone', 'out')"
        >
          <div slot="prefix">
            <img
              v-if="focus === 'telephone' || hover === 'telephone'"
              style="width: 16px;"
              alt=""
              src="@/assets/form/phone-focus.svg"
            />
            <img
              v-else
              style="width: 16px;"
              alt=""
              src="@/assets/form/phone.svg"
            />
            <a-select default-value="+86" style="width: 70px;" :tab-index="-1">
              <a-select-option value="+86"> +86 </a-select-option>
            </a-select>
          </div>
        </a-input>
      </a-form-item>
      <a-form-item>
        <a-input
          v-decorator="[
            'phoneCaptcha',
            { rules: [{ required: true, message: '请输入手机验证码！' }] },
          ]"
          type="phoneCaptcha"
          placeholder="手机验证码"
          class="input"
          @focusin="inputFocus('phoneCaptcha', 'in')"
          @focusout="inputFocus('phoneCaptcha', 'out')"
          @mouseover="inputHover('phoneCaptcha', 'in')"
          @mouseout="inputHover('phoneCaptcha', 'out')"
        >
          <img
            v-if="focus === 'phoneCaptcha' || hover === 'phoneCaptcha'"
            slot="prefix"
            alt=""
            src="@/assets/form/captcha-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/captcha.svg" />
          <a-button v-show="show" slot="addonAfter" @click="getCode">
            发送验证码
          </a-button>
          <span v-show="!show" slot="addonAfter" disabled>
            {{ count }}秒之后可以重新发送
          </span>
        </a-input>
      </a-form-item>
      <a-form-item v-if="showCaptcha">
        <a-input
          v-decorator="['captcha']"
          type="captcha"
          placeholder="验证码"
          class="input"
          @focusin="inputFocus('captcha', 'in')"
          @focusout="inputFocus('captcha', 'out')"
          @mouseover="inputHover('captcha', 'in')"
          @mouseout="inputHover('captcha', 'out')"
        >
          <img
            v-if="focus === 'captcha' || hover === 'captcha'"
            slot="prefix"
            alt=""
            src="@/assets/form/captcha-focus.svg"
          />
          <img v-else slot="prefix" alt="" src="@/assets/form/captcha.svg" />
          <img
            slot="suffix"
            style="height: 28px; width: 90px;"
            alt=""
            :src="`data:text/css;base64,${imageCaptchaCode}`"
            @click="refreshCaptchaCode"
          />
        </a-input>
      </a-form-item>
      <!-- <a-form-item>
        <a-input
          v-decorator="[
            'ecode',
            { rules: [{ required: false, message: '请输入验证码!' }] },
          ]"
          placeholder="验证码"
          class="input"
          @focusin="inputFocus('code','in')"
          @focusout="inputFocus('code','out')"
          @mouseover="inputHover('code','in')"
          @mouseout="inputHover('code','out')"
        >
          <span v-show="show" class="get-code" slot="addonAfter" @click="getCode">获取验证码</span>
          <span v-show="!show" class="count" slot="addonAfter">{{count}}秒之后可以重新发送</span>
        </a-input>
      </a-form-item> -->
      <a-form-item class="agreement-form-item">
        <a-checkbox v-model="isAgreement">
          同意
          <span class="link" @click.stop="openPrivacyAgreementLink"
            >《隐私保护协议》</span
          >
        </a-checkbox>
      </a-form-item>
      <a-form-item>
        <a-button
          type="primary"
          html-type="submit"
          class="register-button"
          :disabled="!isAgreement"
          >注册</a-button
        >
      </a-form-item>
    </a-form>
    <p>
      已有账号？
      <router-link to="/login">去登录</router-link>
    </p>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { getPhoneCaptchaRegister, getImageCaptchaCode } from '@/api/sms'
import { userRegister } from '@/api/user'

@Component
export default class RegisterForm extends Vue {
  private form: any
  // 多次发送手机验证码 显示图片验证码
  private showCaptcha: boolean = false
  // 图片验证码的base64编码
  private imageCaptchaCode: string = ''
  // focus的input
  private focus: string = ''
  // hover的input
  private hover: string = ''

  // 同意 隐私协议， 默认为 false
  private isAgreement = false

  private checkedPasswordLength: boolean = false
  private checkedPasswordNumber: boolean = false
  private checkedPasswordLowerCase: boolean = false
  private checkedPasswordWholeRule: boolean = false

  private passwordRuleList = [
    {
      rule: false,
      text: '8-16个字符',
    },
    {
      rule: false,
      text: '包含数字',
    },
    {
      rule: false,
      text: '包含小写字母',
    },
    {
      rule: false,
      text: '数字、小写字母、大写字母、特殊字符至少包含3种',
    },
  ]

  public openPrivacyAgreementLink(): void {
    const route = this.$router.resolve({
      path: '/privacyAgreement',
    }) as any
    ;(window as any).open(route.href, '_blank')
  }

  beforeCreate() {
    this.form = this.$form.createForm(this, { name: 'register_form' })
  }

  public handleSubmit(event: Event) {
    event.preventDefault()
    this.form.validateFields(async (error: Error, values: any) => {
      if (!error) {
        const passData = {
          name: values.userName,
          password: values.password,
          phone: values.telephone,
          phoneCode: values.phoneCaptcha,
        }
        const response = await userRegister({
          data: passData,
          params: { code: passData.phoneCode },
        })
        if (response.data.code === 100) {
          this.$message.info('注册成功')
          this.$router.push('/user/infos')
        } else if (
          response.data.code === 20007 ||
          response.data.code === 20005
        ) {
          this.$message.error(response.data.message)
        }
      } else {
        console.log('error:', error)
      }
    })
  }

  // 重复输入密码rule
  public checkRepeatPassword(rule: any, value: any, callback: any) {
    if (value !== this.form.getFieldValue('password')) {
      callback('两次密码输入不一致！')
    }
    callback()
  }

  // password 和 repeat password 校验
  public validateToRepeatPassword(rule: any, value: any, callback: any) {
    // 测试密码长度是否为8-16位
    if (/[\S\s]{8,16}/.test(value)) {
      this.passwordRuleList[0].rule = true
    } else {
      this.passwordRuleList[0].rule = false
    }
    // 测试密码是否包含数字
    if (/[\d.]/.test(value)) {
      this.passwordRuleList[1].rule = true
    } else {
      this.passwordRuleList[1].rule = false
    }
    // 测试密码是否包含小写数字
    if (/[.a-z]/.test(value)) {
      this.passwordRuleList[2].rule = true
    } else {
      this.passwordRuleList[2].rule = false
    }
    // 测试密码是否符合全部规则至少包含数字、大写字母、小写字母、特殊字符中的三种类型
    if (
      /^(?![A-Za-z]+$)(?![\dA-Z]+$)(?![\WA-Z_]+$)(?![\da-z]+$)(?![\W_a-z]+$)(?![\W\d_]+$)[\W\w]{3,}$/.test(
        value
      )
    ) {
      this.passwordRuleList[3].rule = true
    } else {
      this.passwordRuleList[3].rule = false
    }

    // 测试密码是否符合全部规则
    if (
      !/^(?![A-Za-z]+$)(?![\dA-Z]+$)(?![\WA-Z_]+$)(?![\da-z]+$)(?![\W_a-z]+$)(?![\W\d_]+$)[\W\w]{8,16}$/.test(
        value
      )
    ) {
      callback(
        '请输入8-16位字符，至少包含数字、大写字母、小写字母、特殊字符中的三种类型'
      )
    }
    if (value && this.form.getFieldValue('repeatPassword')) {
      this.form.validateFields(['repeatPassword'], { force: true })
    }
    callback()
  }

  // 手机号格式rule
  public validateTelephoneNumber(rule: any, value: any, callback: any) {
    if (!value) {
      callback('请输入您的手机号！')
    } else if (!/^1[,3-57-9]\d{9}$/.test(value)) {
      callback('手机号格式错误!')
    } else {
      callback()
    }
  }

  public inputFocus(item: any, type: any) {
    switch (type) {
      case 'in':
        this.focus = item
        break
      case 'out':
        this.focus = ''
        break
      default:
    }
  }

  public inputHover(item: any, type: any) {
    switch (type) {
      case 'in':
        this.hover = item
        break
      case 'out':
        this.hover = ''
        break
      default:
    }
  }

  // 刷新图片验证码
  public async refreshCaptchaCode() {
    const phone = this.form.getFieldValue('telephone')
    const result = await getImageCaptchaCode({ data: phone })
    this.imageCaptchaCode = result.data.result
  }

  private show: boolean = true
  private count: number = 0
  private timer: any = null
  public async getCode() {
    // 间隔60秒
    const TIME_COUNT = 60
    const phone = this.form.getFieldValue('telephone')
    const captchaCode = this.form.getFieldValue('captcha')
    const name = this.form.getFieldValue('userName')
    const password = this.form.getFieldValue('password')
    // 获取手机验证码
    const result = await getPhoneCaptchaRegister(
      captchaCode === ''
        ? {
            data: { phone, name, password },
          }
        : {
            data: { phone, captchaCode, name, password },
          }
    )
    // 根据返回code决定前端
    if (result.data.code === 100) {
      this.$message.success('短信发送成功')
      // 发送成功，设置60秒间隔才能发送
      this.count = TIME_COUNT
      this.show = false
      this.timer = setInterval(() => {
        if (this.count > 0 && this.count <= TIME_COUNT) {
          this.count -= 1
        } else {
          this.show = true
          clearInterval(this.timer)
          this.timer = null
        }
      }, 1000)
    } else if (
      // 需要请求验证码的情况
      result.data.code === 20016 ||
      result.data.code === 20015 ||
      this.showCaptcha === true
    ) {
      this.$message.error(result.data.message)
      this.showCaptcha = true
      const captchaResult = await getImageCaptchaCode({ data: phone })
      this.imageCaptchaCode = captchaResult.data.result
    } else if (
      result.data.code === 20003 ||
      result.data.code === 20006 ||
      result.data.code === 201
    ) {
      this.$message.error(result.data.message)
    }
  }
}
</script>

<style lang="less" scoped>
.input {
  width: 280px;
}

/deep/ .ant-select-selection--single {
  height: 25px;
}

//去除选择器border
/deep/ .ant-select-selection {
  border: 0;
}

// 去除选择器foucus蓝框
/deep/ .ant-select-focused .ant-select-selection,
.ant-select-selection:focus,
.ant-select-selection:active {
  box-shadow: 0 0 0 0;
}

/deep/ .ant-input-affix-wrapper .ant-input-prefix :not(.anticon),
.ant-input-affix-wrapper .ant-input-suffix :not(.anticon) {
  line-height: 2;
}

// 输入框
/deep/ .input .ant-input {
  border: 0;
  border-bottom: 1px solid #e8e8e8;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  font-size: 16px;

  &:not(:first-child) {
    padding-left: 25px;
  }

  &:focus {
    border-bottom: 1px solid #6973ff;
    box-shadow: none;
  }
}

// 手机号输入
/deep/ .telephone-input .ant-input {
  &:not(:first-child) {
    padding-left: 96px;
  }
}

/deep/ .ant-form-explain {
  margin-left: calc(50% - 140px);
  text-align: left;
  width: 280px;
}

// 输入框的前缀图标
/deep/ .input .ant-input-prefix {
  color: #5d637e;
  font-size: 18px;
  left: 0;
}

.success-password-tips {
  align-items: center;
  color: #52c41a;
  display: flex;
  line-height: 22px;
}

.error-password-tips {
  align-items: center;
  color: #7e817d;
  display: flex;
  line-height: 22px;
}

// 行间距
.ant-form-item {
  margin-bottom: 15px;

  &:last-child {
    margin-bottom: 12px;
  }
}

.register-button {
  background: #6973ff;
  border-bottom: 12px;
  border-radius: 17px;
  box-shadow: 0 2px 6px 0 rgba(101, 129, 247, 0.4);
  font-size: 16px;
  height: 34px;
  margin-bottom: 0;
  margin-top: 16px;
  width: 280px;

  &.ant-btn-primary[disabled] {
    background: #ddd;
    box-shadow: none;
  }
}

/deep/ .agreement-form-item {
  .ant-form-item-control {
    margin: 0 auto;
    text-align: left;
    width: 280px;
  }
}

.link {
  color: #6973ff;
  cursor: pointer;
}

/deep/ .ant-input-group-addon {
  background: #fff;
  border: 0;

  .get-code {
    cursor: pointer;
  }

  /deep/ .count {
    color: #5d637e;
    font-size: 14px;
  }
}
</style>
